package com.xygj.vueblog.shiro;

import cn.hutool.json.JSONUtil;
import com.xygj.vueblog.common.lang.Result;
import com.xygj.vueblog.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import jdk.nashorn.internal.parser.Token;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExpiredCredentialsException;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Configuration
public class JwtFilter extends AuthenticatingFilter {

    /**
     *
     * 问题：
     * The bean 'JwtFilter', defined in class path resource [com/xyzq/vueblog/config/ShiroConfig.class], could not be registered.
     * A bean with that name has already been defined in file [xyzq/vueblog/config/ShiroConfig.class] and overriding is disabled.
     *
     * Action:
     *
     * Consider renaming one of the beans or enabling overriding by setting spring.main.allow-bean-definition-overriding=true
     *
     * 简单看一下报错信息，说“could not be registered”，注入失败”
     *
     * 解决方案总结：
     *
     * 1.删除拦截器类级别的@Component注解
     *
     * 2.将配置类中的@Bean改为IOC自动注入
     *
     * 3.application配置文件里加一行：spring.main.allow-bean-definition-overriding: true 。当遇到同样名字的时候，是否允许覆盖注册
     *
     */
    @Autowired
    JwtUtils jwtUtils;
    @Override
    //AuthenticationToken需要实现
    protected AuthenticationToken createToken(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String jwt = request.getHeader("Authorization");
        if (StringUtils.isEmpty(jwt)){
            return null;
        }
        return new JwtToken(jwt);
    }

    @Override
    //拦截
    protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception {

        HttpServletRequest request = (HttpServletRequest)servletRequest;
        String jwt = request.getHeader("Authorization");
        if (StringUtils.isEmpty(jwt)){
            return true;
        }else {//校验jwt

             Claims claim = jwtUtils.getClaimByToken(jwt);

             if (claim ==null || jwtUtils.isTokenExpired(claim.getExpiration())){
                 throw new ExpiredCredentialsException("token已失效，请重新登录");
             }

             //执行登录
            return executeLogin(servletRequest, servletResponse);
        }

    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {

        HttpServletResponse httpServletResponse = (HttpServletResponse)response;
        Throwable throwable = e.getCause() == null ? e : e.getCause();

        Result result = Result.fail(throwable.getMessage());

        String json = JSONUtil.toJsonStr(result);

        try {
            httpServletResponse.getWriter().print(json);
        } catch (IOException ex) {

        }
        return false ;
    }
}
